﻿#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SOCKET_ERROR -1
#define BUF_SIZE 1024
void ErrorHandle(const std::string &msg)
{
  std::cout << msg << "error!" << std::endl;
  exit(-1);
}
void Print(const std::string &msg)
{
  std::cout << msg << std::endl;
}
int main(int args, char *argv[])
{
  int caculate(int length, int *, char opt);
  // step01:创建套接字
  int sock_serv, sock_clnt;
  if ((sock_serv = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
    ErrorHandle("socket() error!");
  Print("socket() ok ...");
  // step02:设置IP和端口号port
  sockaddr_in addr_serv;
  memset(&addr_serv, 0, sizeof(addr_serv));
  addr_serv.sin_family = AF_INET;
  addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
  addr_serv.sin_port = htons(atoi(argv[1])); // atoi将字符串转为整型
  if (bind(sock_serv, (sockaddr *)&addr_serv, sizeof(addr_serv)) == SOCKET_ERROR)
    ErrorHandle("bind() error!");
  Print("bind() ok ...");
  // step03:进入等待请求连接状态
  if (listen(sock_serv, 5) == -1)
    ErrorHandle("listen() error!");
  Print("listen() ok ...");
  sockaddr_in addr_clnt;
  char opinfo[BUF_SIZE];
  socklen_t sizeaddrclnt = sizeof(addr_clnt);
  char msg[BUF_SIZE];
  for (int i = 1; i <= 10; ++i)
  {
    // step04:进入数据传输阶段
    sock_clnt = accept(sock_serv, (sockaddr *)&addr_clnt, &sizeaddrclnt);
    if (sock_clnt == SOCKET_ERROR)
      ErrorHandle("accept() error!");
    Print("accept() ok ...");
    std::cout << "Connected client " << i << std::endl;
    // step05:传输数据
    char len;
    recv(sock_clnt, &len, 1, 0);
    int length = int(len - 48);
    int recv_len = 0;
    while ((4 * length + 1) > recv_len)
    {
      int cur_len = recv(sock_clnt, &opinfo[recv_len], BUF_SIZE - 1, 0);
      recv_len += cur_len;
    }
    int result = caculate(length, (int *)opinfo, opinfo[recv_len - 1]);
    std::cout << "ok" << std::endl;
    send(sock_clnt, (char *)&result, sizeof(result), 0);
    close(sock_clnt);
  }
  close(sock_serv);
  return 0;
}

int caculate(int length, int *nums, char opt)
{
  int result = nums[0];
  switch (opt)
  {
  case '+':
    for (int i = 1; i < length; i++)
      result += nums[i];
    break;
  case '-':
    for (int i = 1; i < length; i++)
      result -= nums[i];
    break;
  case '*':
    for (int i = 1; i < length; i++)
      result *= nums[i];
    break;
  }
  return result;
}